import React from 'react';
import {Row, Col, message, List, Tooltip, TreeSelect, Button} from 'antd';
import {isEmpty, isFunction, findIndex, forEach, map, isObject, isArray, isString} from 'lodash-es';
import styles from './index.module.less';
import UploadDragger from '../UploadDragger';
import classNames from 'classnames';
import {recurAddKeyAndFileds, byte2KOM, getRandomKey, getStorage, jhMultiply,} from 'jh-utils';
import PhotoSwiper from '../PhotoSwiper';
import ModalComp from '../ModalItem/ModalComp';
import {
    FileOutlined,
    DeleteOutlined,
    CloseCircleOutlined,
    CheckCircleOutlined,
    LoadingOutlined
} from "@ant-design/icons";
import BaseComp from "../Base/BaseComp";
import {docListApi, uploadDocApi} from "../../services/uploadApi";
import PhotoUpload from "../PhotoUploadModal";
import {STORAGE_KEY} from "../Config";
import {jhMessage} from "../../utils/base";
import { getDefaultImageType } from "../../utils/utils";

/**
 *  上传
 */
export default class FileUploadComp extends BaseComp {
    static defaultProps = {
        uploadApi: uploadDocApi.api,
        isModal: true,
        autoHide: false, // 上传完成之后，默认关闭
        boxHeight: 0,
        accept: '', // 接收的文件类型，以 ',' 分隔
        needDir: true, // 是否需要文件夹
        selectedDirKeys: [],
        hideModal: () => {
        },
        onUploadDone: null, // ({dirId, files}) => void 所有文件上传完成之后的回调
        onChangeUploaded: null, // (uploadedFiles, allFiles) => void 每次有文件上传完成之后，都会回调这个方法
        uploadFileRowCb: null, // (uploadTemp) => void 选择文件之后的回调
    };

    itemRef;
    /**
     * 预上传文件
     */
    uploadTemp;
    /**
     * 上传成功的文件
     */
    usFile;

    uploadDragRef;

    constructor(props) {
        super(props);
        this.itemRef = React.createRef();
        this.state = {
            mode: 'top',
            previewFile: null,
            dirId: '',
            isShowPS: false, // 是否显示图片预览浮层
            curFile: {}, // 当前预览的文件
            compUpdateTime: Math.floor(Math.random() * 10000),
            dirTreeComp: [],//要上传的文件中心目录
        };
        this.uploadTemp = [];
        this.usFile = [];  //上传成功的文件
    }

    componentDidMount() {
        this.props.onRef && (this.props.onRef(this));
        // if (this.props.dirTreeComp && isEmpty(this.props.dirTreeComp)) {
        //     this.fetchList();
        // }
        if (this.props.needDir) {
            this.fetchList();

            if (!isEmpty(this.props.selectedDirKeys) && this.props.selectedDirKeys) {
                this.setState({
                    dirId: this.props.selectedDirKeys[0],
                });
            }
        }
    }

    componentDidUpdate(prevProps, prevState) {
        // “关闭”操作
        if (prevProps.visible && !this.props.visible) {
            // 如果不是正在上传，清空临时变量
            if (!this.isUploading()) {
                this.uploadTemp = [];
                this.usFile = [];  //上传成功的文件
            }
        }
    }

    /**
     * 获取文件信息
     * @param payload
     */
    fetchList(payload = {}) {
        // const {dispatch, compData} = this.props;
        this.reqGet(docListApi.api).then(res => {
            if (isObject(res) && 200 === res.status && res.data) {
                this.setState({
                    dirTreeComp: res.data.results || [],
                });
            }
        })
    }

    /**
     * 选择本地图片之后的回调
     * @param fileObj Object 图片对象，包含两个字段：{thumbUrl:"String 图片的 base64 数据，只有图片类型有这个字段", originFileObj:'File 本地文件资源'}
     */
    onBeforeUploadCb(fileObj) {
        const {uploadFileRowCb} = this.props;
        // console.log("fileObj:",fileObj);
        if (fileObj && fileObj.originFileObj) {
            // 判断文件大小是否超出限制
            const userInfo = getStorage(STORAGE_KEY.USER_INFO);
            if (userInfo && userInfo.environment && userInfo.environment.maxFileSize > 0) {
                let tmpSize = parseInt(userInfo.environment.maxFileSize);
                let maxFileSize = jhMultiply(isNaN(tmpSize) ? 0 : tmpSize, 1024);
                if (maxFileSize > 0 && maxFileSize < fileObj.originFileObj.size) {
                    // 'comp.upload.size.fail': '上传失败：文件不得超过{size}',
                    jhMessage.error(this.myFormatMessage('comp.upload.size.fail', {size: byte2KOM(maxFileSize)}));
                    return false;
                }
            }


            this.uploadTemp.push(fileObj);
            // let tempList = [...uploadTemp, fileObj];
            this.setState({
                compUpdateTime: Math.floor(Math.random() * 10000),
            }, () => {
                // props.uploadFileRowCb 只是为了控制外部的按钮
                uploadFileRowCb &&
                uploadFileRowCb(this.uploadTemp);
            });
        }
    }

    getFileUploadTemp() {
        return this.uploadTemp;
    };

    //删除临时附件信息
    onDeleteUploadTemp(uid) {
        const {uploadFileRowCb} = this.props;
        // if (findIndex(this.uploadTemp, (o) => {
        //   return o.uid == uid;
        // }) != -1) {
        //   this.closePreviewCb();//清除预览效果
        // }
        this.uploadTemp = this.uploadTemp.filter((item) => item.uid !== uid);
        if (isEmpty(this.uploadTemp)) this.uploadTemp = [];
        this.setState({
            compUpdateTime: Math.floor(Math.random() * 10000),
        }, () => {
            uploadFileRowCb &&
            uploadFileRowCb(this.uploadTemp);
        });
    }

    onClickFile(item, e) {
        e.stopPropagation();
        if (item.thumbUrl) {
            this.setState({isShowPS: true, curFile: item});
        }
    }

    dealImgs() {

        if (isEmpty(this.uploadTemp)) return [];

        return this.uploadTemp.filter((v) => (v && v.thumbUrl && v.originFileObj))
            .map(this._dealFile2Photo);
    }

    _dealFile2Photo(v) {
        if (isEmpty(v)) return {};
        // let originFileObj = v.originFileObj;
        // let defaultImg = getDefaultImageType(originFileObj && originFileObj.name);
        return ({
            uid: v.uid,
            name: v.originFileObj.name,
            src: v.thumbUrl,
        });
    }

    /**
     * 选中目录
     * @param dir
     */
    onChange = (dir) => {
        this.setState({
            dirId: dir,
        });
        this.props.setCurrentDirId &&
        this.props.setCurrentDirId(dir, 'upload');
    };

    selectTree(list) {
        // console.log('list：',list);
        const loop = (data) => data.map((item) => {
            if (item.children && item.children.length) {
                return <TreeSelect.TreeNode value={item.id}
                                            title={item.name}>{loop(item.children)}</TreeSelect.TreeNode>;
            }
            return <TreeSelect.TreeNode value={item.id}
                                        title={item.name}/>;
        });

        return (
            <TreeSelect
                style={{width: '100%'}}
                placeholder="请选择目录"
                treeDefaultExpandAll
                onChange={this.onChange}
                defaultValue={this.props.selectedDirKeys}
            >
                {loop(list)}
            </TreeSelect>
        );
    }

    //文件路径下拉框\tab1
    filePathSelectView = () => {
        // const {dirTreeComp} = this.props;
        let {dirTreeComp} = this.state;
        dirTreeComp = !isEmpty(this.props.dirTreeComp) ? this.props.dirTreeComp : dirTreeComp;
        let tree = recurAddKeyAndFileds(dirTreeComp);
        // let tree  = dirTreeComp;// recurAddKeyAndFileds();
        //console.log('tree:',tree);
        return (
            <Row>
                <Col span={4} style={{height: '32px', lineHeight: '32px'}}> <label>文件路径:</label></Col>
                <Col span={20} style={{paddingRight: 10}}>
                    {this.selectTree(tree)}
                </Col>
            </Row>
        );
    };

    //文件上传
    handleUpload = () => {
        const {dirId} = this.state;
        const uploadTemp = this.uploadTemp;

        console.log('FileUploadComp handleUpload uploadTemp', this.uploadTemp);

        // if (1 > dirId) {
        //     message.info('请选择目录');
        //     return false;
        // }

        //上传的文件
        let tmpFile = null;
        forEach(uploadTemp, (file) => {

            if (tmpFile === null && (typeof file.upload_status == 'undefined' || file.upload_status < 1)) {
                tmpFile = file;
                // let formData = new FormData();
                // formData.append('file', file.originFileObj);
                // this.upload(formData, dirId, file);
            }

            if (typeof file.upload_status == 'undefined') {
                file.upload_status = 0;
            }
        });

        if (isEmpty(tmpFile)) {
            message.info('请先选择文件');
            return false;
        }

        if (tmpFile) {
            let formData = new FormData();
            formData.append('file', tmpFile.originFileObj);
            this.upload(formData, dirId, tmpFile);
        }
    };

    upload = (formData, dirId, fileInfo) => {
        fileInfo.upload_status = 3;// 标识加载中

        this.reRender(() => {
            this.props.onChangeUploaded && this.props.onChangeUploaded(this.usFile, this.uploadTemp);
        });

        let $this = this;
        this.requestFunc(this.props.uploadApi, {
            method: 'POST',
            data: formData,
            contentType: 'multipart/form-data',
            params: {},
        }).then((res) => {
            let rsp = res ? res.data || {} : {};
            let status = 0; // 等待上传
            if (isObject(rsp) && 200 === rsp.status) {
                status = 1; //上传成功
                let fileInd = findIndex($this.uploadTemp, (obj) => {
                    return obj.uid === fileInfo.uid;
                });
                if (fileInd !== -1) {
                    //@ts-ignore
                    if (isObject(rsp.data)) {
                        //@ts-ignore
                        $this.uploadTemp[fileInd] = {...$this.uploadTemp[fileInd], ...rsp.data};
                        //@ts-ignore
                    } else if (isString(rsp.data)) {
                        //@ts-ignore
                        const strArr = `${rsp.data}`.split('/');
                        $this.uploadTemp[fileInd]['name'] = fileInfo.originFileObj.name;
                        //@ts-ignore
                        $this.uploadTemp[fileInd]['savePath'] = rsp.data;
                        $this.uploadTemp[fileInd]['saveName'] = strArr[strArr.length - 1];
                        $this.uploadTemp[fileInd]['size'] = fileInfo.originFileObj.size;
                        $this.uploadTemp[fileInd]['ext'] = `${strArr[strArr.length - 1]}`.substr(`${strArr[strArr.length - 1]}`.lastIndexOf('.'));
                    }

                    $this.usFile.push($this.uploadTemp[fileInd]);
                }
            } else {
                status = 2;//上传失败
            }
            this.setUploadFileState(fileInfo, status);
        });
    };

    setUploadFileState(info, status) {
        const uploadTemp = this.uploadTemp, {dirId} = this.state;

        if (!isEmpty(uploadTemp) && isArray(uploadTemp)) {
            let fileInd = findIndex(uploadTemp, (obj) => {
                return obj.uid === info.uid;
            });

            if (fileInd !== -1) {
                uploadTemp[fileInd]['upload_status'] = status;

                if (1 == status) {
                    //检测是否有重复文件
                    let tempInd = findIndex(this.usFile, (obj) => {
                        return obj.uid == uploadTemp[fileInd]['uid'];
                    });
                    if (tempInd < 0) {
                        this.usFile.push(uploadTemp[fileInd]);
                    }
                }
                this.setState({
                    randomKey: getRandomKey()
                });
            }

            //检测所有文件是否已上传？
            let isSuccessful = true;
            let nextUnLoadFile = null;
            forEach(uploadTemp, (obj) => {
                if (typeof obj.upload_status == 'undefined' || obj.upload_status < 1) {
                    isSuccessful = false;
                    nextUnLoadFile = obj;
                    return false;
                }
            });

            if (isSuccessful === true) {
                // message.info('上传完成');
                let hadUploadFail = this.hadUploadFail();
                this.props.onUploadDone && this.props.onUploadDone({dirId: dirId, files: this.usFile});
                // 设置了默认关闭，而且没有文件上传失败，则默认关闭弹框
                if (this.props.autoHide && !hadUploadFail) {
                    isFunction(this.props.hideModal) && this.props.hideModal();
                    return;
                }
            } else if (nextUnLoadFile) {
                // 如果没上传完，则继续上传下一个文件
                let formData = new FormData();
                formData.append('file', nextUnLoadFile.originFileObj);
                this.upload(formData, dirId, nextUnLoadFile);
                return;
            }

        }

        this.props.onChangeUploaded && this.props.onChangeUploaded(this.usFile, this.uploadTemp);
    }

    async handleOk() {

        const {beforeUpload} = this.props;
        if (isFunction(beforeUpload)) {
            // upload_errmsg
            let funcReturn = beforeUpload(this.uploadTemp);

            if (false === funcReturn) return false;

            if (funcReturn instanceof Promise) {
                return funcReturn.then(() => {
                    this.handleUpload();
                }).catch(uploadTemp => {
                    this.uploadTemp = uploadTemp;
                    this.reRender();
                })
            }
        }
        this.handleUpload();
    };

    handleCancel(e) {
        this.props.hideModal();
    }

    hadUploadFail() {
        let had = false;

        if (!isEmpty(this.uploadTemp)) {
            forEach(this.uploadTemp, (item) => {
                if (2 === item.upload_status) {
                    had = true;
                    return false;
                }
            });
        }
        return had;
    }

    isDisabledConfirm() {
        let isDisabled = true;

        if (!isEmpty(this.uploadTemp)) {
            forEach(this.uploadTemp, (item) => {
                if (typeof item.upload_status == 'undefined' || 3 === item.upload_status) {
                    isDisabled = false;
                    return false;
                }
            });
        }
        return isDisabled;
    }

    isUploading() {
        let uploading = false;
        map(this.uploadTemp, (item) => {
            if (3 === item.upload_status) {
                uploading = true;
                return false;
            }
        });
        return uploading;
    }

    mainRender() {
        const {previewFile, compUpdateTime, curFile} = this.state,
            {isModal, boxHeight, accept, needMediaUpload} = this.props;
        let isDisabledConfirm = this.isDisabledConfirm();
        let isUploading = this.isUploading();
        const uploadTemp = this.uploadTemp;
        const photoList = this.dealImgs();
        const curPhotoInd = curFile && curFile.uid ? findIndex(photoList, (v, k) => (v && v.uid === curFile.uid)) : 0;
        let height = boxHeight ? boxHeight : document.body.offsetHeight - 300;
        let draggerStyle = {
            marginTop: 10, paddingRight: 10,
            height: height - 42
        };
        if (!this.props.needDir) {
            draggerStyle.height = height;
            draggerStyle.marginTop = 0;
        }
        const layouts = (
            <Row className={styles.fileUploadWarp}>
                <Col span={12}>
                    <Row>
                        {
                            this.props.needDir && (
                                <Col span={24}>{this.filePathSelectView()}</Col>
                            )
                        }
                        <Col span={24} style={draggerStyle}>
                            <div style={{height: needMediaUpload ? '50%' : '100%'}}>
                                <UploadDragger
                                    onRef={ref => this.uploadDragRef = ref}
                                    accept={accept}
                                    isPreviewMode={previewFile != null && '' != previewFile}
                                    key={compUpdateTime}
                                    previewFile={previewFile}
                                    onBeforeUploadCb={this.onBeforeUploadCb.bind(this)}
                                    // closePreviewCb={this.closePreviewCb.bind(this)}
                                    // changeUploadCb={this.changeUploadCb.bind(this)}
                                />
                            </div>
                            {
                                needMediaUpload ?
                                    <div style={{height: '50%'}} onClick={() => this.setState({phVisible: true})}>
                                        <PhotoUpload
                                            {...this.props}
                                            onBeforeUploadCb={this.onBeforeUploadCb.bind(this)}
                                        />
                                    </div> : null
                            }

                        </Col>
                    </Row>
                </Col>
                <Col span={12} className={styles.fileList} style={{height: height}}>
                    <List dataSource={uploadTemp}
                          renderItem={(item) => {
                              let originFileObj = item.originFileObj;
                              let defaultImg = getDefaultImageType(originFileObj && originFileObj.name);

                              return <div className={styles.fileContainer}>
                                  <div className={styles.filePic}
                                       onClick={this.onClickFile.bind(this, item)}
                                  >
                                      {
                                          item.thumbUrl ? (
                                              <img src={item.thumbUrl} alt={'图片'}/>
                                          ) :  <img src={defaultImg} alt={''}/>
                                      }

                                  </div>
                                  <div className={styles.fileDetails}
                                       onClick={this.onClickFile.bind(this, item)}>
                                      <div className={styles.fileName} title={item.originFileObj.name}>
                                          {item.originFileObj.name}
                                      </div>
                                      <div className={styles.filePath}>{byte2KOM(item.originFileObj.size)}</div>
                                  </div>
                                  {
                                      (0 === item.upload_status) &&
                                      <span className={classNames(styles.uploadStatus)}>
                                             等待上传
                                      </span>
                                  }
                                  {
                                      (1 === item.upload_status) &&
                                      <span className={classNames(styles.uploadStatus, styles.succeed)}>
                                              <CheckCircleOutlined/> 已上传
                                      </span>
                                  }
                                  {
                                      (2 === item.upload_status) &&
                                      <span className={classNames(styles.uploadStatus, styles.error)}>
                                              <CloseCircleOutlined/> 上传失败
                                      </span>
                                  }
                                  {
                                      (3 === item.upload_status) &&
                                      <span className={classNames(styles.uploadStatus, styles.primary)}>
                                              <LoadingOutlined/> 上传中
                                      </span>
                                  }
                                  {
                                      (!isEmpty(item.upload_errmsg)) &&
                                      <span className={classNames(styles.uploadStatus, styles.error)}>
                                              <CloseCircleOutlined/> {item.upload_errmsg}
                                      </span>
                                  }
                                  <Button className={styles.fileDelete}
                                          type={"link"}
                                          disabled={3 === item.upload_status}
                                          onClick={e => {
                                              e.stopPropagation();
                                              this.onDeleteUploadTemp(item.uid);
                                          }}>
                                      <DeleteOutlined/>
                                  </Button>
                              </div>
                          }}/>
                    <PhotoSwiper
                        visible={this.state.isShowPS}
                        onClose={() => {
                            this.setState({isShowPS: false});
                        }}
                        curInd={curPhotoInd}
                        photoList={photoList}
                    />
                </Col>
            </Row>
        );

        return (
            isModal === true ?
                <ModalComp
                    // destroyOnClose={true}
                    title={`上传文件`}
                    width={document.body.offsetWidth > 1200 ? document.body.offsetWidth * 0.5 : '70%'}
                    visible={this.props.visible}
                    onOk={this.handleOk.bind(this)}
                    okText={this.formatMsgByCn('确认上传')}
                    cancelText={this.formatMsgByCn('关闭')}
                    okButtonProps={{
                        disabled: isDisabledConfirm,
                        loading: isUploading
                    }}
                    onCancel={this.handleCancel.bind(this)}
                    {
                        ...(this.props.modalProps || {})
                    }
                >
                    {layouts}
                </ModalComp> : layouts
        );
    }
}




